package com.czk.volatiles;

import java.util.HashSet;
import java.util.Set;

/**
 * 指令重排序的测试
 * 在不影响单线程程序执行结果的情况下，计算机为了最大限度的发挥机器的性能，会对机器指令重排序优化
 * 重排序会遵从as-if-serial原则和happen-before的原则
 * 内存屏障：
 * volatile a
 * 对a的读写操作进行读写屏障的添加
 * loadLoad load1 loadLoad load2 保证load1的读操作在load2及后续读取操作之后之前执行
 * storeStore store1 storeStore store2 保证store2及其以后的写操作执行前，保证store1的写操作已经刷新到主存
 * loadStore load loadStore store 在store及其以后的写操作执行前，保证load的读操作已经结束
 * storeLoad store storeLoad load保证store的写操作已经刷新到主存后,load及其以后的操作才执行
 *
 * @Author:ChenZhangKun
 * @Date: 2021/3/30 17:48
 */
public class VolatileSerialTest {
    /**
     * volatile防止指令重排序
     * 可以防止对象得到半初始化的问题
     */
    static volatile int x = 0, y = 0;
    static volatile int a = 0, b = 0;

    public static void main(String[] args) throws InterruptedException {
        // 定义集合
        Set<Integer> set = new HashSet<>();
        for (int i = 0; i < 1000000; i++) {
            x = 0;
            y = 0;
            a = 0;
            b = 0;
            Thread first = new Thread(() -> {
                a = y;
                x = 1;
            });
            Thread second = new Thread(() -> {
                b = x;
                y = 1;
            });
            first.start();
            second.start();
            first.join();
            second.join();
            set.add(a);
            set.add(b);
            // 可能会指令重排， 出现 a=1 b=1的情况
            System.out.println(set);
        }
    }
}
